//
//  Base1TableViewController.swift
//  APP
//
//  Created by LXF on 2018/1/5.
//  Copyright © 2018年 Rdxer. All rights reserved.
//

import UIKit
import XXLogger
import Moya
import RxSwift
import MBProgressHUD
import HandyJSON

/// 实现 "下拉加载","上拉加载更多" 的父类
/**
需要进行重写的   ⬇️⬇️⬇️⬇️⬇️⬇️⬇️
 
 override func loadDataApiTarget(needLoadPage: Int) throws -> MessageApi {
    return .news(newtype: type, page: needLoadPage)
 }
 
 override func loadMoreDataApiTarget(needLoadPage: Int) throws -> MessageApi {
    return .news(newtype: type, page: needLoadPage)
 }

 ⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️
 
 需要实现的泛型
 <APIType:TargetType,  请求的 target
 ModelClass:HandyJSON, 解析的模型
 CellClass:XXBaseTableViewCell<ModelClass>>  cell
 
*/

class BaseLoadAndLoadMoreTableViewController<APIType:TargetType,ModelClass:HandyJSON,CellClass:XXBaseTableViewCell<ModelClass>>: XXBaseTableViewController {

    open let api = APIProviderManager.makeProvider() as MoyaProvider<APIType>
    
    lazy fileprivate var page:Int = {
        return defaultPage()
    }()
    
    open func defaultPage()->Int{
        return 1
    }
    
    open func currentyPage()->Int{
        return page
    }
    
    open var dataList:[ModelClass] = []
    
    open var hud:MBProgressHUD?
    
    //********************************************************************************
    ///// 需要进行重写的   ⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️
    
    ///  api.rx.request(._(_ page: 1.description))  下拉刷新
    open func loadDataApiTarget(needLoadPage:Int)throws->APIType{
        throw NSError.init(domain: "请实现此方法并且返回值", code: -1, userInfo: nil)
    }
    
    /// api.rx.request(._(_page: (page+1).description))  上拉加载更多
    open func loadMoreDataApiTarget(needLoadPage:Int)throws->APIType{
        throw NSError.init(domain: "请实现此方法并且返回值", code: -1, userInfo: nil)
    }
    //⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️⤴️
    //********************************************************************************
    
    override open func viewDidLoad() {
        super.viewDidLoad()
        prepareTableView()
        self.xx.emptyDataSetStatu = XXEmptyDataSetStatu.loading
    }
    
    // MARK: - prepareTableView
    open func prepareTableView(){
        
        self.automaticallyAdjustsScrollViewInsets = false
        tableView.tableFooterView = UIView.init()
        tableView.backgroundColor = AppColor.backgroundColor
        tableView.estimatedRowHeight = 100
        
        //        tableView.separatorInset = .init(top: <#T##CGFloat#>, left: <#T##CGFloat#>, bottom: <#T##CGFloat#>, right: <#T##CGFloat#>)
        //        tableView.separatorStyle = .none
        registerCell()
        prepareRefreshHeaderIfNeed()
        startLoad()
    }
    
    open func startLoad(){
        hud = addTransparentHUDTo(self.tableView)
        loadData()
    }
    
    open func needRegisterCells()->[String:CellClass.Type]{
        return [
            "cell":CellClass.self
        ]
    }

    open func registerCell(){
        needRegisterCells().forEach { (key,value) in
            tableView.register(value, forCellReuseIdentifier: key)
        }
    }
    
    
    
    open func prepareRefreshHeaderIfNeed() {
        if tableView.header_safe != nil{
            return
        }
        tableView.prepareRefreshHeader(refreshingTarget: self, refreshingAction: #selector(loadData))
    }
    
    func prepareRefreshFooterIfNeed(){
        if tableView.footer_safe != nil{
            return
        }
        tableView.prepareRefreshFooter(refreshingTarget: self, refreshingAction: #selector(loadMoreData))
    }

    
    
    // MARK: -
    // MARK: - loadData && loadMoreData
    @objc open func loadData(){
        self.dispose = DisposeBag.init()
        let apiTarget = try! loadDataApiTarget(needLoadPage: defaultPage())
        api.rx.request(apiTarget)
//            .filterWhenNeedRefreshToken(target: self, sel: #selector(loadData))
            .mapModelListWithDataValue(ModelClass.self)
            .subscribe(onSuccess: {[weak self] (dataList) in
                self?.hud?.hide(animated: true)
                self?.prepareEmptyDataSetIfNeed(scrollView: self!.tableView)
                if let dataList = dataList as? [ModelClass],
                    dataList.count > 0
                {
                    self?.prepareRefreshFooterIfNeed()
                    self?.dataList = dataList
                    
                    if dataList.count < ServerConfig.page_size{
                        self?.tableView.footer_safe?.endRefreshingWithNoMoreData()
                    }else{
                        self?.tableView.footer_safe?.resetNoMoreData()
                    }
                    
                }else{
                    self?.dataList = []
                    self?.tableView.footer_safe = nil // 移除
//                    self?.tableView.footer_safe?.endRefreshingWithNoMoreData()
                }
                self?.tableView.header_safe?.endRefreshing()
                self?.page = self?.defaultPage() ?? 1
                self?.xx.emptyDataSetStatu = XXEmptyDataSetStatu.emptyData
                self?.tableView.reloadData()
            }) { [weak self](err) in
                self?.hud?.hide(animated: true)
                self?.tableView.header_safe?.endRefreshing()
                self?.prepareEmptyDataSetIfNeed(scrollView: self!.tableView)
                self?.xx.emptyDataSetStatu = XXEmptyDataSetStatu.emptyData
                self?.tableView.reloadEmptyDataSet()
                showErrorHUD(err)
            }.disposed(by: self)
        
    }
    
    @objc open func loadMoreData(){
        let apiTarget = try! loadMoreDataApiTarget(needLoadPage: page+1)
        api.rx.request(apiTarget)
//            .filterWhenNeedRefreshToken(target: self, sel: #selector(loadMoreData))
            .mapModelListWithDataValue(ModelClass.self)
            .subscribe(onSuccess: { [weak self](dataList) in
                if let dataList = dataList as? [ModelClass],
                    dataList.count > 0
                {
                    self?.page = (self?.page ?? 1) + 1
                    self?.dataList += dataList
                    
                    if dataList.count < ServerConfig.page_size{
                        self?.tableView.footer_safe?.endRefreshingWithNoMoreData()
                    }else{
                        self?.tableView.footer_safe?.endRefreshing()
                    }
                    
                }else{
                    self?.tableView.footer_safe?.endRefreshingWithNoMoreData()
                }
                self?.tableView.reloadData()
            }) { [weak self](err) in
                self?.tableView.footer_safe?.endRefreshing()
                showErrorHUD(err)
            }.disposed(by: self)
    }

    // MARK: -
    // MARK: - Table view data source
    override open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataList.count
    }
    
    open func cellId(at model:ModelClass,indexPath:IndexPath,tableView: UITableView)->String{
        if let model = model as? XXBaseTableViewCellIdProvideProtocol {
            return model.cellId(indexPath)
        }
        return "cell"
    }
    
    override open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let model = modelAt(indexPath)
        
        let cellid = cellId(at: model, indexPath: indexPath, tableView: tableView)
        
        let cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as! CellClass
        
        
        cell.model = model
        
        prepareCell(cell: cell, model: model, tableView: tableView, indexPath: indexPath)
        
        return cell
    }
    
    /// 如果重写了 tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
    /// 则此方法不会自动调用
    open func prepareCell(cell:CellClass,model:ModelClass,tableView: UITableView,indexPath: IndexPath){
        
    }
    
    open func modelAt(_ indexPath:IndexPath)->ModelClass{
        return dataList[indexPath.row]
    }
    
    override open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        /// 点击动画实现
        tableView.deselectRow(at: indexPath, animated: true)
        let model = modelAt(indexPath)
        self.tableView(tableView, didSelectRowAt: indexPath, model: model)
    }
    /// cell 点击事件
    open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath,model:ModelClass) {
        
    }
}



